/*
 * Copyright (c) 2011 Imre Fazekas.
 * All rights reserved.
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 *
 * Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 * Neither the name of the Brillien nor the names of its
 * terms and concepts may be used to endorse or promote products derived from this
 * software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

package com.vii.brillien.kernel.axiom.atomic;

import com.vii.brillien.kernel.BrillienException;
import com.vii.brillien.kernel.axiom.atomic.component.CharacteristicFunction;
import com.vii.brillien.kernel.axiom.atomic.component.EquivalenceRelation;
import com.vii.brillien.kernel.axiom.atomic.component.OrderRelation;
import com.vii.brillien.kernel.axiom.transport.Communication;

import java.util.Collection;

/**
 * Set-like Presence type. May collect Presence instances as a logical reference set.
 * The Units must be arranged into a graph describing logical connection between unit instances
 */
public interface Unit <P extends Presence, C extends Communication, R> extends Presence<C, R>{


    /*
    *
    * -------------------------------------------------------------------------
    *                           Set as Presence
    * -------------------------------------------------------------------------
    *
    * */


    /**
     * Gets the characteristic function associated to the given Unit.
     * @return characteristic function
     */
    <T> CharacteristicFunction<P,C,T> getCharacteristicFunction();

    /**
     * Setter method for the CharacteristicFunction associated to the given Unit.
     * @param function CharacteristicFunction to be associated
     */
    <T> void                setCharacteristicFunction( CharacteristicFunction<P,C,T> function );

    /**
     * Gets subunit instances
     * @return subunits
     */
    Collection<Unit>        getSubUnits();

    /**
     * Adds new subunits. The readding is filtered
     * @param ses array of new subunits
     */
    Unit<P,C,R>             addSubUnits( Unit... ses) throws BrillienException;

    /**
     * Removes subunits.
     * @param ses array of subunits to remove
     */
    Unit<P,C,R>             removeSubUnits( Unit... ses) throws BrillienException;

    /**
     * Clears all subunits
     */
    void                    clearSubUnits() throws BrillienException;

    /**
     * Gets all Presences included into this unite instance
     * @return included Presences
     */
    Collection<Presence>    getPresences() ;

    /**
     * Checks if the Presence could became set element
     * @param p element candidate presence
     * @throws BrillienException in case of element rule violation
     */
    void                    scrutinise( Presence p ) throws BrillienException;

    /**
     * Adds new Presences. The readding is filtered
     * @param ses array of new Presences
     */
    void                    addPresences( P... ses) throws BrillienException;

    /**
     * Removes Presences.
     * @param ses array of Presences to remove
     */
    void                    removePresences( P... ses) throws BrillienException;

    /**
     * Clears all Presences
     */
    void                    clearPresences() throws BrillienException;

    /**
     * Subset creation from the given Unit
     * @param function CharacteristicFunction of the subset
     * @return subset
     */
    Unit<P,C,R>             subset( CharacteristicFunction<P,C,R> function ) throws BrillienException;

    /**
     * Creates union set from the actual and the given Unit
     * @param unit other part of the unio set
     * @return union set
     */
    Unit<P,C,R>             union( Unit<P,C,R> unit ) throws BrillienException;

    /**
     * Creates intersect set from the actual and the given Unit
     * @param unit other part of the intersect set
     * @return intersect set
     */
    Unit<P,C,R>             intersect( Unit<P,C,R> unit ) throws BrillienException;

    /**
     * Creates complement set from the actual and the given Unit
     * @param unit other part of the complement set
     * @return complement set
     */
    Unit<P,C,R>             complement( Unit<P,C,R> unit ) throws BrillienException;

    /**
     * Creates symmetric difference set from the actual and the given Unit
     * @param unit other part of the symmetric difference set
     * @return symmetric difference set
     */
    Unit<P,C,R>             symmetricDifference( Unit<P,C,R> unit ) throws BrillienException;

    /**
     * Classifies the unit by using an equivalence relation
     * @param function equivalence relation
     * @return collection of element classes
     * @throws BrillienException
     */
    Collection<Unit>        classify( EquivalenceRelation<P,C,R> function ) throws BrillienException;

    /**
     * Orders the presences of the unit by using an order relation
     * @param function order relation
     * @return collection of ordered presences
     * @throws BrillienException
     */
    Collection<P>           order( OrderRelation<P,C,R> function ) throws BrillienException;

    /**
     * Decides whether the given parameter is subset of the actual Unit instance
     * @param u set instance
     * @return result of the investigation on subset property
     */
    boolean                 isSubSet( Unit<P,C,R> u );



    /*
    *
    * -------------------------------------------------------------------------
    *                           Set as Unit 
    * -------------------------------------------------------------------------
    *
    * */

    /**
     * Notification method about an incoming message addressed to this all Sensors of this Unit.
     * @param message message object received
     * @throws com.vii.brillien.kernel.BrillienException Exception thrown in a problematic situation
     */
    void                    communicationUnitReceived( C message  ) throws BrillienException;

    /**
     * Makes all presences in this unit to be retrieved by the proper Presencemanagers
     */
    void                    retrieveUnit() throws BrillienException;

    /**
     * Tells whether a Presence in this Unit has callable activity
     */
    boolean                 hasUnitActivity();

    /**
     * Makes all Presences in this Unit active
     */
    void                    activateUnitMessaging() throws BrillienException;

    /**
     * Makes all Presences in this Unit passive.
     */
    void                    passivateUnitMessaging() throws BrillienException;

    /**
     * Activates the callable activity of all Presences in this Unit.
    */
    void                    activateUnitCallable() throws BrillienException;

    /**
     * Passivates the callable activity of all Presences in this Unit.
    */
    void                    passivateUnitCallable() throws BrillienException;

    /**
     * Tells whether an Aspirer in this Unit is waiting an answer to a redirected get-like message sent earlier.
     */
    boolean                 isUnitWaitingForResponse();

    /**
     * Tells whether the presences in this unit are in exit state. 
     */
    boolean                 isUnitInExitState();


    String                  printUnitErrorStates( );

    /**
     * Tells whether the presences in this unit are in valid states
     */
    boolean                 isUnitInValidStates();

    /**
     * Activates all Presences in this Unit.
     */
    void                    activateUnitAll( ) throws BrillienException;

    /**
     * Passivates all Presences in this Unit.
     */
    void                    passivateUnitAll( ) throws BrillienException;

}
